#include <iostream>
#include <string>
#include <unistd.h>
#include <vector>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task.hpp"

// 信道
class Channel
{
public:
    Channel(int wfd, pid_t subprocessid, const std::string &name)
        : _wfd(wfd), _subprocessid(subprocessid), _name(name)
    {
    }
    int GetWfd()
    {
        return _wfd;
    }
    pid_t GetSubId()
    {
        return _subprocessid;
    }
    std::string GetChannelName()
    {
        return _name;
    }
    void CloseChannel()
    {
        close(_wfd);
    }
    void WaitSubProcess()
    {
        pid_t rid = waitpid(_subprocessid, nullptr, 0);
        if (rid > 0)
        {
            std::cout << "wait " << rid << "success!" << std::endl;
        }
    }
    ~Channel()
    {
        _wfd = 0;
        _subprocessid = 0;
    }

private:
    int _wfd;
    pid_t _subprocessid;
    std::string _name;
};
void SubProcessWork()
{
    while (true)
    {
        int TaskCommand = 0;
        int n = read(0, &TaskCommand, sizeof TaskCommand);
        if (n == sizeof(int))
        {
            EecuteTask(TaskCommand);
        }
        else
        {
            std::cout << "TASK执行完毕,子进程退出" << std::endl;
            break;
        }
    }
}

void CreateChannel_With_SubProcess(int num, std::vector<Channel> *channels,task_t task)
{
    for (int i = 0; i < num; i++)
    {
        // Create a pipeline
        int pipefd[2] = {0};
        int n = pipe(pipefd);
        if (n < 0)
        {
            std::cerr << "Pipe creator failed !" << std::endl;
            exit(1);
        }
        // Create Process
        pid_t id = fork();
        if (id == 0)
        {
            // Child Process
            close(pipefd[1]);
            dup2(pipefd[0],0);
            task();
            close(pipefd[0]);
            exit(0);
        }
        // Create one Channel_name
        std::string Channel_name = "Channel-" + std::to_string(i);
        // Father Process working areas;
        close(pipefd[0]);
        channels->push_back(Channel(pipefd[1], id, Channel_name));
    }
}
int NextChannel(int Channelnum)
{
    // 轮询
    static int next = 0;
    int IndexChannel = next;
    ++next;
    next %= Channelnum;
    return IndexChannel;
}
void SendTaskCommand(Channel &channel, int taskcode)
{
    write(channel.GetWfd(), &taskcode, sizeof taskcode);
}
void CtrlProcess(std::vector<Channel> &channels)
{
    int taskcode = SelectTask();
    int ChannelIndex = NextChannel(channels.size());
    SendTaskCommand(channels[ChannelIndex], taskcode);
}
void CtrlProcessLoop(std::vector<Channel> &channels, int time = -1)
{
    if (time == -1)
    {
        while (true)
        {
            CtrlProcess(channels);
        }
    }
    else 
    {
        while(time--)
        {
            CtrlProcess(channels);
        }
    }
}

void DeleteChannel(std::vector<Channel> &channels)
{
    // 关闭wfd
    for (auto &channel : channels)
    {
        channel.CloseChannel();
    }
    // 等待子进程
    for (auto &channel : channels)
    {
        channel.WaitSubProcess();
    }
}
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cerr << "RIGHT Usage: " << argv[0] << "processNum " << std::endl;
        return -1;
    }
    // 取出要创建的进程数量
    int num = std::stoi(argv[1]);
    std::vector<Channel> channels;
    // 加载任务
    LoadTasks();
    // 创建Channel和子进程
    CreateChannel_With_SubProcess(num, &channels,SubProcessWork);
    // 2.通过Channel管理子进程-->传递任务码给子进程
    CtrlProcessLoop(channels);
    // 3.销毁Channel
    DeleteChannel(channels);
    return 0;
}